﻿using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.ComponentModel.DataAnnotations;
using System.Runtime.Serialization;
using Kyoh.App.Crawler.Plugin;
using Kyoh.Lib.Component;
using Kyoh.Lib.Component.Globalization;

namespace Kyoh.App.Crawler.Contents
{
    [Serializable]
    class Anchor : ISeed, IAnchor
    {
        public Anchor()
        {
            Data = new StringDictionary();
        }

        public Anchor(IAnchor anchor)
            : this()
        {
            if (anchor.Data != null)
                foreach (DictionaryEntry d in anchor.Data)
                    Data.Add((string)d.Key, (string)d.Value);
            _dateTime = anchor.DateTime;
            _title = anchor.Title;
            _uri = anchor.Uri;
            _range = anchor.Range;
            _tag = anchor.Tag;
            _pieceId = anchor.PieceId;
        }

        public const string PropertyNameTitle = "Title";
        public const string PropertyNameUri = "Uri";
        public const string PropertyNameRange = "Range";
        public const string PropertyNameTag = "Tag";
        public const string PropertyNameDateTime = "DateTime";
        public const string PropertyNamePieceId = "PieceId";
        public const string PropertyNameData = "Data";

        #region IAnchor メンバー
        private string _title;
        [DisplayNameFromResource(typeof(Properties.DisplayName), PropertyNameTitle)]
        [PropertyIndex(0)]
        [Editable(false)]
        [DisplayAutoSize(DisplayAutoSizeMode.NameAndValues)]
        public string Title
        {
            get { return _title; }
            set
            {
                if (_title == value)
                    return;
                OnPropertyChanging(PropertyNameTitle);
                _title = value;
                OnPropertyChanged(PropertyNameTitle);
            }
        }
        private string _uri;
        [DisplayNameFromResource(typeof(Properties.DisplayName), PropertyNameUri)]
        [PropertyIndex(1)]
        [Editable(false)]
        [DisplayAutoSize(DisplayAutoSizeMode.NameAndValues)]
        public string Uri
        {
            get { return _uri; }
            set
            {
                if (_uri == value)
                    return;
                OnPropertyChanging(PropertyNameUri);
                _uri = value;
                OnPropertyChanged(PropertyNameUri);
            }
        }
        private long _range;
        [Browsable(false)]
        public long Range
        {
            get { return _range; }
            set
            {
                if (_range == value)
                    return;
                OnPropertyChanging(PropertyNameRange);
                _range = value;
                OnPropertyChanged(PropertyNameRange);
            }
        }
        private string _tag;
        [Browsable(false)]
        public string Tag
        {
            get { return _tag; }
            set
            {
                if (_tag == value)
                    return;
                OnPropertyChanging(PropertyNameTag);
                _tag = value;
                OnPropertyChanged(PropertyNameTag);
            }
        }
        private DateTime _dateTime;
        [DisplayNameFromResource(typeof(Properties.DisplayName), PropertyNameDateTime)]
        [PropertyIndex(2)]
        [Editable(false)]
        [DisplayAutoSize(DisplayAutoSizeMode.NameAndValues)]
        public DateTime DateTime
        {
            get { return _dateTime; }
            set
            {
                if (_dateTime == value)
                    return;
                OnPropertyChanging(PropertyNameDateTime);
                _dateTime = value;
                OnPropertyChanged(PropertyNameDateTime);
            }
        }
        private long _pieceId;
        [Browsable(false)]
        public long PieceId
        {
            get { return _pieceId; }
            set
            {
                if (_pieceId == value)
                    return;
                OnPropertyChanging(PropertyNamePieceId);
                _pieceId = value;
                OnPropertyChanged(PropertyNamePieceId);
            }
        }
        [Browsable(false)]
        public StringDictionary Data { get; private set; }
        #endregion

        #region ISeed メンバー

        public const string PropertyNamePriority = "Priority";
        private SeedPriority _priority;

        [Browsable(false)]
        public string UniqueKey
        {
            get { return Uri; }
        }

        [PropertyIndex(2)]
        [DisplayAutoSize(DisplayAutoSizeMode.NameAndValues)]
        [DisplayNameFromResource(typeof(Properties.DisplayName), PropertyNamePriority)]
        [EnumDataType(typeof(SeedPriority))]
        public SeedPriority Priority
        {
            get { return _priority; }
            set
            {
                if (_priority == value)
                    return;
                OnPropertyChanging(PropertyNamePriority);
                _priority = value;
                OnPropertyChanged(PropertyNamePriority);
            }
        }

        [Browsable(false)]
        public bool Run
        {
            get { return false; }
        }

        #endregion

        #region INotifyPropertyChanging メンバー

        public event PropertyChangingEventHandler PropertyChanging;
        protected virtual void OnPropertyChanging(string propertyName)
        {
            OnPropertyChanging(new PropertyChangingEventArgs(propertyName));
        }
        protected virtual void OnPropertyChanging(PropertyChangingEventArgs e)
        {
            var handler = PropertyChanging;
            if (handler != null)
                handler(this, e);
        }

        #endregion

        #region INotifyPropertyChanged メンバー

        public event PropertyChangedEventHandler PropertyChanged;
        protected virtual void OnPropertyChanged(string propertyName)
        {
            OnPropertyChanged(new PropertyChangedEventArgs(propertyName));
        }
        protected virtual void OnPropertyChanged(PropertyChangedEventArgs e)
        {
            var handler = PropertyChanged;
            if (handler != null)
                handler(this, e);
        }

        #endregion

        #region ISerializable メンバー
        protected Anchor(SerializationInfo info, StreamingContext context)
        {
            _title = info.GetString(PropertyNameTitle);
            _uri = info.GetString(PropertyNameUri);
            _range = info.GetInt64(PropertyNameRange);
            _tag = info.GetString(PropertyNameTag);
            _dateTime = info.GetDateTime(PropertyNameDateTime);
            _pieceId = info.GetInt64(PropertyNamePieceId);
            Data = (StringDictionary)info.GetValue(PropertyNameData, typeof(StringDictionary));
            _priority = (SeedPriority)info.GetValue(PropertyNamePriority, typeof(SeedPriority));
        }
        public void GetObjectData(SerializationInfo info, StreamingContext context)
        {
            info.AddValue(PropertyNameTitle, _title);
            info.AddValue(PropertyNameUri, _uri);
            info.AddValue(PropertyNameRange, _range);
            info.AddValue(PropertyNameTag, _tag);
            info.AddValue(PropertyNameDateTime, _dateTime);
            info.AddValue(PropertyNamePieceId, _pieceId);
            info.AddValue(PropertyNameData, Data);
            info.AddValue(PropertyNamePriority, _priority);
        }
        #endregion
    }
}
